package com.egg.ylt.Utils;

import android.support.annotation.NonNull;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.method.LinkMovementMethod;
import android.text.style.CharacterStyle;
import android.text.style.ClickableSpan;
import android.text.style.ForegroundColorSpan;
import android.text.style.RelativeSizeSpan;
import android.text.style.StrikethroughSpan;
import android.util.Log;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created By Dlx
 * on 2018/12/3 0003
 * 设置关键字高亮工具，后续会扩展添加其他功能，使用方式见注释
 * 可缩放字体
 * 可添加删除线
 */
public class StringSpanUtils {
    private static StringSpanUtils utils;
    private static List<SpannableStringBuilder> builderList;

    private StringSpanUtils() {
    }

    /**
     * 初始化工具，用以链式调用
     *
     * @return
     */
    public static StringSpanUtils init() {
        if (utils == null) {
            utils = new StringSpanUtils();
            builderList = new ArrayList<>();
        }
        return utils;
    }

    /**
     * 添加普通字符串，不参与匹配修改
     *
     * @param str
     * @return
     */
    public StringSpanUtils addStr(String str) {
        if (isNotEmpty(str))
            builderList.add(new SpannableStringBuilder(str));
        return utils;
    }

    /**
     * 添加字符串，关键字改变颜色（高亮）
     *
     * @param color     颜色
     * @param targetStr 字符串
     * @param key       关键字
     * @return
     */
    public StringSpanUtils addForegroundColorHighLightWithKey(int color, String targetStr, String key) {
        if (isNotEmpty(targetStr) && isNotEmpty(key)) {
            SpannableStringBuilder ssb = new SpannableStringBuilder(targetStr);
            CharacterStyle span;
            Pattern pattern = Pattern.compile(checkKey(key));
            Matcher matcher = pattern.matcher(targetStr);
            while (matcher.find()) {
                span = new ForegroundColorSpan(color);
                ssb.setSpan(span, matcher.start(), matcher.end(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            }
            builderList.add(ssb);
        }
        return utils;
    }

    /**
     * 添加字符串，整串变色
     *
     * @param color
     * @return
     */
    public StringSpanUtils addForegroundColorHighLight(int color, String targetStr) {
        if (isNotEmpty(targetStr)) {
            CharacterStyle span;
            SpannableStringBuilder ssb = new SpannableStringBuilder(targetStr);
            span = new ForegroundColorSpan(color);
            ssb.setSpan(span, 0, targetStr.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            builderList.add(ssb);
        }
        return utils;
    }

    /**
     * 添加字符串，关键字相对缩放（float）
     *
     * @param scale 缩放比例
     * @param key   关键字
     * @return
     */
    public StringSpanUtils addRelativeScaleWithKey(float scale, String targetStr, String key) {
        if (isNotEmpty(targetStr) && isNotEmpty(key)) {
            if (scale <= 0.0f) {
                scale = 1.0f;
            }
            SpannableStringBuilder ssb = new SpannableStringBuilder(targetStr);
            CharacterStyle span;
            Pattern pattern = Pattern.compile(checkKey(key));
            Matcher matcher = pattern.matcher(targetStr);
            while (matcher.find()) {
                span = new RelativeSizeSpan(scale);
                ssb.setSpan(span, matcher.start(), matcher.end(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            }
            builderList.add(ssb);
        }
        return utils;
    }

    /**
     * 添加字符串并整体缩放
     *
     * @param scale
     * @param targetStr
     * @return
     */
    public StringSpanUtils addRelativeScale(float scale, String targetStr) {
        if (isNotEmpty(targetStr)) {
            if (scale <= 0.0f) {
                scale = 1.0f;
            }
            SpannableStringBuilder ssb = new SpannableStringBuilder(targetStr);
            CharacterStyle span;
            span = new RelativeSizeSpan(scale);
            ssb.setSpan(span, 0, targetStr.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            builderList.add(ssb);
        }
        return utils;
    }

    /**
     * 设置第position位置的字符串，额外按关键字添加删除线
     *
     * @param key
     * @param position
     * @return
     */
    public StringSpanUtils setDeleteLineWithKeyAndPosition(String key, int position) {
        if (isNotEmpty(key)) {
            if (checkBounds(position)) {
                SpannableStringBuilder ssb = builderList.get(position);
                CharacterStyle span;
                Pattern pattern = Pattern.compile(checkKey(key));
                Matcher matcher = pattern.matcher(ssb);
                while (matcher.find()) {
                    span = new StrikethroughSpan();
                    ssb.setSpan(span, matcher.start(), matcher.end(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                }
            }
        }
        return utils;
    }

    /**
     * 设置第position位置的字符串，额外按关键字添加颜色
     *
     * @param key
     * @param position
     * @param color
     * @return
     */
    public StringSpanUtils setForeColorWithKeyAndPosition(String key, int position, int color) {
        if (isNotEmpty(key)) {
            if (checkBounds(position)) {
                SpannableStringBuilder ssb = builderList.get(position);
                CharacterStyle span;
                Pattern pattern = Pattern.compile(checkKey(key));
                Matcher matcher = pattern.matcher(ssb);
                while (matcher.find()) {
                    span = new ForegroundColorSpan(color);
                    ssb.setSpan(span, matcher.start(), matcher.end(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                }
            }
        }
        return utils;
    }

    /**
     * 设置第position位置的字符串，额外按关键字添加缩放效果
     *
     * @param key
     * @param position
     * @param scale
     * @return
     */
    public StringSpanUtils setScaleWithKeyAndPosition(String key, int position, float scale) {
        if (isNotEmpty(key)) {
            if (checkBounds(position)) {
                if (scale <= 0.0f) {
                    scale = 1.0f;
                }
                SpannableStringBuilder ssb = builderList.get(position);
                CharacterStyle span;
                Pattern pattern = Pattern.compile(checkKey(key));
                Matcher matcher = pattern.matcher(ssb);
                while (matcher.find()) {
                    span = new RelativeSizeSpan(scale);
                    ssb.setSpan(span, matcher.start(), matcher.end(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                }
            }
        }
        return utils;
    }

    /**
     * 设置可点击的部分字体
     *
     * @param position
     * @param clickableSpan
     * @param textView
     * @return
     */
    public StringSpanUtils setClickableWithPosition(int position, @NonNull ClickableSpan clickableSpan, TextView textView) {
        if (checkBounds(position)) {
            textView.setMovementMethod(LinkMovementMethod.getInstance());
            SpannableStringBuilder ssb = builderList.get(position);
            ssb.setSpan(clickableSpan, 0, ssb.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
        }
        return utils;
    }

    /**
     * 关键字检查
     *
     * @param key
     * @return
     */
    private String checkKey(String key) {
        if (key == null)
            return null;
        StringBuilder stringBuilder = new StringBuilder();
        if (key.contains("*") || key.contains("(") || key.contains(")")) {
            char[] chars = key.toCharArray();
            for (int k = 0, length = chars.length; k < length; k++) {
                if (chars[k] == '*' || chars[k] == '(' || chars[k] == ')') {
                    stringBuilder.append("\\").append(chars[k]);
                } else {
                    stringBuilder.append(chars[k]);
                }
            }
        } else {
            stringBuilder.append(key);
        }
        stringBuilder.insert(0, "(?i)");
        return stringBuilder.toString();
    }

    private boolean isNotEmpty(String str) {
        if (str == null || "".equals(str))
            return false;
        return true;
    }

    /**
     * 检查position边界，越界操作不生效
     *
     * @param position
     * @return
     */
    private boolean checkBounds(int position) {
        if (builderList.size() == 0) {
            return false;
        }
        if (position < 0) {
            return false;
        }
        if (position >= builderList.size()) {
            return false;
        }
        return true;
    }


    /**
     * 完成创建，并释放资源
     *
     * @return
     */
    public SpannableStringBuilder build() {
        SpannableStringBuilder temp = new SpannableStringBuilder();
        for (int i = 0, length = builderList.size(); i < length; i++) {
            temp.append(builderList.get(i));
        }
        utils = null;
        builderList = null;
        return temp;
    }
}
